package com.googlecode.hmvc4gwt.example.hmvcblog.service.services.user;

import java.util.Date;

import javax.persistence.EntityExistsException;
import javax.persistence.NoResultException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.EmailValidator;
import org.springframework.beans.factory.annotation.Autowired;

import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.user.User;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.IUserRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.exceptions.UserExistException;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.exceptions.UserNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.exceptions.UserSessionNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserEditDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserLoginDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserLogoutDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserNewDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserRemoveDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserSessionId;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.EMailInvalidException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.LoginEmptyException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.LoginExistException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.LoginNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.PasswordEmptyException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.PasswordWrongException;

public class UserService implements IUserService {

	private IUserRepository userRepository;

	private Log log = LogFactory.getLog(UserService.class);

	public Long addUser(UserNewDTO userNewDTO) throws LoginExistException,
			PasswordEmptyException, LoginEmptyException, EMailInvalidException {

		log.info("Adding User: " + userNewDTO.getLogin());

		if ((userNewDTO.getLogin() == null)
				|| (userNewDTO.getLogin().equals(""))) {
			throw new LoginEmptyException();
		}

		if ((userNewDTO.getLogin() == null)
				|| (userNewDTO.getPassword().equals(""))) {
			throw new PasswordEmptyException();
		}

		if (!EmailValidator.getInstance().isValid(userNewDTO.getEmail())) {
			throw new EMailInvalidException();
		}

		try {
			User user = new User();
			user.setEmail(userNewDTO.getEmail());
			user.setLogin(userNewDTO.getLogin());
			user.setForeName(userNewDTO.getForeName());
			user.setPassword(userNewDTO.getPassword());
			user.setSureName(userNewDTO.getSureName());

			setSessionId(user);

			getUserRepository().storeUser(user);

			return user.getSessionId();

		} catch (EntityExistsException e) {

			throw new LoginExistException();

		} catch (Exception e) {

			log.error(e.getStackTrace());
			return null;
		}

	}

	public IUserRepository getUserRepository() {
		return userRepository;
	}

	public Long login(UserLoginDTO userLoginDTO) throws LoginEmptyException,
			PasswordEmptyException, LoginNotFoundException,
			PasswordWrongException {

		if ((userLoginDTO.getLogin() == null)
				|| (userLoginDTO.getLogin().equals(""))) {
			throw new LoginEmptyException();
		}

		if ((userLoginDTO.getPassword() == null)
				|| (userLoginDTO.getPassword().equals(""))) {
			throw new PasswordEmptyException();
		}

		try {
			User user = getUserRepository()
					.findByLogin(userLoginDTO.getLogin());

			if (user.getPassword().equals(userLoginDTO.getPassword())) {

				/*
				 * aktuelle SessionId setzen
				 */
				setSessionId(user);
				getUserRepository().updateUser(user);

				return user.getSessionId();

			} else {
				throw new PasswordWrongException();
			}

		} catch (NoResultException e) {

			log.error(e);
			throw new LoginNotFoundException();

		} catch (UserNotFoundException e) {

			log.error(e);
			throw new LoginNotFoundException();

		}

	}

	public boolean logout(UserLogoutDTO userLogoutDTO) {

		if (userLogoutDTO == null) {
			return true;
		}

		try {
			User user = getUserRepository().findBySessionId(
					userLogoutDTO.getSessionId());

			user.setSessionId(0L);
			getUserRepository().updateUser(user);

			return true;

		} catch (UserSessionNotFoundException e) {
			log.error(e);
			return false;
		}

	}

	public boolean removeUser(UserRemoveDTO userRemoveDTO) {

		if (userRemoveDTO == null) {
			log.error("userRemoveDTO is null");
			return false;
		}

		try {
			User user = getUserRepository().findById(userRemoveDTO.getIdUser());

			getUserRepository().removeUser(user);

			return true;

		} catch (UserNotFoundException e) {
			log.error(e);
			return false;
		}

	}

	@Autowired
	public void setUserRepository(IUserRepository userRepository) {
		this.userRepository = userRepository;
	}

	private void setSessionId(User user) {

		user.setSessionId(generateSessionId());

	}

	private long generateSessionId() {
		return new Date().getTime();
	}

	public UserEditDTO getUserEditDTO(UserSessionId sessionId)
			throws UserSessionNotFoundException {

		User user = getUserRepository().findBySessionId(
				sessionId.getSessionId());

		UserEditDTO userEditDTO = new UserEditDTO();
		userEditDTO.setLogin(user.getLogin());
		userEditDTO.setEmail(user.getEmail());
		userEditDTO.setForeName(user.getForeName());
		userEditDTO.setSureName(user.getSureName());

		return userEditDTO;
	}

	public void updateUserData(UserEditDTO userEditDTO)
			throws PasswordEmptyException, EMailInvalidException,
			UserSessionNotFoundException {

		if (!EmailValidator.getInstance().isValid(userEditDTO.getEmail())) {
			throw new EMailInvalidException();
		}

		User user = getUserRepository().findBySessionId(
				userEditDTO.getSessionId());

		user.setEmail(userEditDTO.getEmail());
		user.setForeName(userEditDTO.getForeName());

		if (!userEditDTO.getPassword().equals("")) {
			user.setPassword(userEditDTO.getPassword());
		}

		user.setSureName(userEditDTO.getSureName());

		try {
			getUserRepository().storeUser(user);
		} catch (UserExistException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
